package ph.com.gs3.chat;

import java.util.List;

import ph.com.gs3.chat.fragments.interfaces.CallbackCommand;
import ph.com.gs3.chat.fragments.view.OnlineUsersViewFragment;
import ph.com.gs3.chat.fragments.view.OnlineUsersViewFragment.OnlineUsersViewActionListener;
import ph.com.gs3.chat.fragments.worker.LoginWorkerFragment;
import ph.com.gs3.chat.fragments.worker.MainWorkerFragment;
import ph.com.gs3.chat.model.valueobject.business.User;
import ph.com.gs3.chat.model.valueobject.business.UserStub;
import ph.com.gs3.chat.services.NotifierService;
import ph.com.gs3.chat.utilities.FLLogger;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends Activity implements OnlineUsersViewActionListener {

	public static final String TAG = MainActivity.class.getSimpleName();

	public static final String EXTRA_ACTIVE_USER = "active_user";

	private OnlineUsersViewFragment viewFragment;
	// private TestViewFragment viewFragment;
	private MainWorkerFragment workerFragment;

	// private boolean isNotificationServiceBound;

	// services
	// private NotificationListenerService connectedNotificationListenerService;

	private Intent notificationHandlerServiceIntent;

	// temporary only
	public static final int SOCKET_PORT = 3013;

	// ==============================================================================
	// {{ Life Cycle Listeners

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initializeFieldsAndFlags();
		initializeFragments(savedInstanceState);

		startNotificationService();
		getAndDisplayOnlineUsers();

	}

	@Override
	public void onResume() {
		super.onResume();

		registerBroadcastReceivers();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();

		switch (id) {
			case R.id.action_settings: {}
				break;
			case R.id.action_logout: {
				FLLogger.d(TAG, "logout");
				if (notificationHandlerServiceIntent != null) {
					stopService(notificationHandlerServiceIntent);
				}

				finish();
			}
				break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();

		unregisterBroadcastReceivers();
	}

	// }}

	// ==============================================================================
	// {{ Initialization Methods

	private void initializeFieldsAndFlags() {
		// isNotificationServiceBound = false;
		// TODO: add other fields to initialize here
	}

	private void initializeFragments(Bundle savedInstanceState) {

		FragmentManager manager = getFragmentManager();
		FragmentTransaction transaction = manager.beginTransaction();

		// set the view fragment
		if (savedInstanceState == null) {

			viewFragment = new OnlineUsersViewFragment();
			// viewFragment = new TestViewFragment();
			transaction.add(R.id.container, viewFragment);

		}

		// set the worker fragment
		workerFragment = (MainWorkerFragment) manager.findFragmentByTag(MainWorkerFragment.TAG);
		if (workerFragment == null) {

			Intent intent = getIntent();
			Bundle extras = intent.getExtras();

			if (!extras.containsKey(EXTRA_ACTIVE_USER)) {
				throw new IllegalArgumentException("The " + EXTRA_ACTIVE_USER
				        + " is required for this activity");
			}

			User currentlyActiveUser = (User) extras.getSerializable(EXTRA_ACTIVE_USER);
			workerFragment = MainWorkerFragment.createInstance(currentlyActiveUser);
		}

		transaction.add(workerFragment, LoginWorkerFragment.TAG);
		transaction.commit();

	}

	// }}

	// ======================================================================
	// {{ Functional Methods

	private void startNotificationService() {

		notificationHandlerServiceIntent = new Intent(MainActivity.this,
		        NotifierService.class);

		User currentlyActiveUser = workerFragment.getCurrentlyActiveUser();

		notificationHandlerServiceIntent.putExtra(
		        NotifierService.EXTRA_CURRENT_USER, currentlyActiveUser);
		notificationHandlerServiceIntent.putExtra(NotifierService.EXTRA_PORT,
		        SOCKET_PORT);

		startService(notificationHandlerServiceIntent);

	}

	private void getAndDisplayOnlineUsers() {

		workerFragment.getOnlineUsers(new CallbackCommand<List<UserStub>>() {

			@Override
			public void execute(List<UserStub> result) {

				User currentUser = workerFragment.getCurrentlyActiveUser();

				viewFragment.setImageServer(currentUser.getAccountServer());
				viewFragment.clearUsers();
				viewFragment.addUsers(result);
			}
		});

	}

	private void registerBroadcastReceivers() {
		// notification listener service filter
		IntentFilter nlServiceFilter = new IntentFilter();

		// TODO: below are all the actions available, remove the unused actions later
		nlServiceFilter.addAction(NotifierService.ACTION_ON_CONNECTED);
		nlServiceFilter.addAction(NotifierService.ACTION_ON_DISCONNECTED);
		nlServiceFilter.addAction(NotifierService.ACTION_ON_USER_LOGGED_IN);
		nlServiceFilter.addAction(NotifierService.ACTION_ON_USER_LOGGED_OUT);
		nlServiceFilter
		        .addAction(NotifierService.ACTION_ON_NOTIFICATION_RECEIVED);
		// nlServiceFilter.addAction(RealTimeEventsManagerKeeperService.ACTION_ON_MESSAGE_RECEIVED);

		nlServiceFilter.addCategory(Intent.CATEGORY_DEFAULT);

		registerReceiver(notificationsListener, nlServiceFilter);

	}

	private void unregisterBroadcastReceivers() {
		unregisterReceiver(notificationsListener);
	}

	// }}

	// ======================================================================
	// {{ View Implementation Methods

	@Override
	public void onOnlineUserClicked(UserStub user) {

		User currentUser = workerFragment.getCurrentlyActiveUser();
		UserStub currentUserStub = new UserStub();

		currentUserStub.setId(currentUser.getId());
		currentUserStub.setDisplayName(currentUser.getDisplayName());
		currentUserStub.setImageURL(currentUser.getImageURL());

		Intent chatActivityIntent = new Intent(MainActivity.this, ChatActivity.class);
		chatActivityIntent.putExtra(ChatActivity.EXTRA_CURRENT_USER_STUB, currentUserStub);
		chatActivityIntent.putExtra(ChatActivity.EXTRA_USER_STUB, user);
		startActivity(chatActivityIntent);

	}

	// }}

	private BroadcastReceiver notificationsListener = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {

			Bundle extras = intent.getExtras();
			String action = intent.getAction();

			FLLogger.d(TAG, "action received: " + action);

			// connection & disconnection

			if (NotifierService.ACTION_ON_CONNECTED.equals(action)) {
				Toast.makeText(MainActivity.this, "You are now connected to socket server",
				        Toast.LENGTH_LONG).show();
			}

			if (NotifierService.ACTION_ON_DISCONNECTED.equals(action)) {
				Toast.makeText(MainActivity.this, "You have been disconnected to socket server",
				        Toast.LENGTH_LONG).show();
			}

			// user related

			if (NotifierService.ACTION_ON_USER_LOGGED_IN.equals(action)) {

				UserStub user = (UserStub) extras
				        .getSerializable(NotifierService.EXTRA_LOGGED_IN_USER);
				viewFragment.addUser(user);

				FLLogger.d(TAG, user.getDisplayName() + " logged in");
			}

			if (NotifierService.ACTION_ON_USER_LOGGED_OUT.equals(action)) {

				UserStub user = (UserStub) extras
				        .getSerializable(NotifierService.EXTRA_LOGGED_OUT_USER);
				viewFragment.removeUser(user.getId());

				FLLogger.d(TAG, user.getDisplayName() + " logged out");

			}

			// notifications

			if (NotifierService.ACTION_ON_NOTIFICATION_RECEIVED.equals(action)) {

			}

		}

	};

}
